﻿//
// Created by hujin on 2020/10/6.
//

#include "ast_function.h"
#include "ast_statements.h"
#include "ast_def.h"
#include "../logger.h"


void ParamsNode::addToTable(SymbolTable* table) {
	for (const auto& x : params) {
		if(!table->pushSymbol(x.second, Identifier_Data(x.first ? ID_VAR_I : ID_VAR_C))){
		    log_error(3, "dup param name", getLine(), getPos());
		    log_error2('b', getLine());
		}
		data.push_back(table->getDiscriptions(x.second));
	}
}

void ParamsNode::putFunctionToTable(SymbolTable* table, FunctionHeadNode* headNode) {
	if(!table->pushSymbol(headNode->name, Identifier_Data(headNode->retInt ? ID_FUNC_I : ID_FUNC_C, this))){
        log_error(3, "dup function name", getLine(), getPos());
        log_error2('b', getLine());
	}
}

void ParamsNode::putVoidFuncToTable(SymbolTable* table, std::string& name) {
    if(!table->pushSymbol(name, Identifier_Data(ID_VOID, this))){
        log_error(3, "dup function name", getLine(), getPos());
        log_error2('b', getLine());
    }
}

const std::vector<std::pair<bool, std::string>> &ParamsNode::getParams() const {
    return params;
}


void ParamsNode::genCodeRead(Synthesizer *syn, MemoryAllocator *memNew) {
    int pos = 0;
    for(auto i : params){
        memNew->readFromParam(data[pos++].uid, params.size());
    }
}

bool FunctionNode::checkError(SymbolTable *table) {
    //有返回值的函数缺少return语句或存在不匹配的return语句
    if( !(statements->getStatements()->containsReturn(false, head->retInt)) &&
        !statements->getStatements()->containsReturn(true, false) &&
        !statements->getStatements()->containsReturn(false, !head->retInt)){
        log_error(3, "missing return value", getLine(), getPos());
        log_error2('h', getLine());
        return false;
    }
    return true;
}

void FunctionNode::genCode(Synthesizer *syn, MemoryAllocator *mem) {
    syn->text<< getLabelName(head->name)<<':'<<std::endl;
    paramsNode->genCodeRead(syn, mem);
    statements->genCode(syn, mem);
    mem->save_global_changes();
    syn->text<<"jr $31"<<std::endl;
}

void FunctionVoidNode::genCode(Synthesizer *syn, MemoryAllocator *mem) {
    syn->text<< getLabelName(name)<<':'<<std::endl;
    paramsNode->genCodeRead(syn, mem);
    statements->genCode(syn, mem);
    mem->save_global_changes();
    syn->text<<"jr $31"<<std::endl;
}

bool FunctionVoidNode::checkError(SymbolTable *table) {
//    if( statements->getStatements()->containsReturn(false, false) ||
//        statements->getStatements()->containsReturn(false, true)){
//        log_error(3, "Contains invalid return value", getLine(), getPos());
//        log_error2('g', getLine());
//        return false;
//    }
    return true;
}



void BodyNode::genCode(Synthesizer *out, MemoryAllocator *allocator) {
    if(varDef != nullptr)varDef->genCode(out, allocator, false);
    if(statements != nullptr)statements->genCode(out, allocator);
}

std::string getLabelName(std::string func) {
    return func.insert(0, "label_");
}
